package com.cyd.spring;

import com.cyd.service.UserService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @version 1.0.0
 * Created by cyd on 2024-07-31 15:43:02
 * @ClassName : com.cyd.spring.CydBeanPostProcessor
 * @Description : 后置处理器实现类
 */
@Component
public class AopBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(String beanName, Object bean) {
        if (beanName.equals("userService")) {
            System.out.println(this.getClass().getSimpleName() + " do postProcessBeforeInitialization : " + bean);
        }
        return bean;
    }

    /**
     * aop的实现原理
     */
    @Override
    public Object postProcessAfterInitialization(String beanName, final Object bean) {
        if (bean instanceof UserService) {

            System.out.println(this.getClass().getSimpleName() + " : do postProcessAfterInitialization : " + bean);
            if (true) {// 如果被设置切面，则使用动态代理
                Object proxyInstance = Proxy.newProxyInstance(this.getClass().getClassLoader(),
                        bean.getClass().getInterfaces(),
                        new InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                if (true) { // 判断该方法是否被设置CutPoint
                                    System.out.println(this.getClass().getSimpleName() + ":如果method被标记为@Before 执行切面逻辑");
                                }
                                Object result = method.invoke(bean, args);
                                if (true) { // 判断该方法是否被设置CutPoint
                                    System.out.println(this.getClass().getSimpleName() + ":如果method被标记为@After 执行切面逻辑");
                                }
                                return result;
                            }
                        });
                System.out.println(this.getClass().getSimpleName() + " : 返回代理类 : " + proxyInstance);
                // 如果被设置切面，需要aop，返回动态代理对象，这样将来执行invoke时，才会被增强；
                return proxyInstance;
            }

            // 如果没有被设置切面，不需要aop，不需要动态代理，直接返回bean
            return bean;

        }


        return bean;
    }
}
